package main

import "fmt"

/*
1、为什么需要继承
(1)在实现一个结构体时，可能会出现代码冗余，而且代码不利于维护，同时也不利于功能的扩展
(2)解决方法：通过继承方式来解决代码复用
2、基本介绍
继承可以解决代码复用，编程更加靠近人类思维
当多个结构体存在相同的属性(字段)和方法时，可以从这些结构体中抽象出结构体，在该结构体中定义这些相同的属性和方法
其他的结构体不需要重新定义这些属性和方法，只需嵌套一个Student匿名结构体即可
也就是说：在go中，如果一个struct嵌套了另一个匿名结构体，那么这个结构体可以直接访问匿名结构体的字段和方法，从而实现了继承特性
3、基本语法
type Goods struct{
	Name string
	Price int
}
type Book struct{
	Goods //这里就是嵌套匿名结构体Goods
	Writer strings
}
4、优点
(1)代码复用性提高了
(2)代码的扩展性和维护性提高了
*/
//编写一个学生考试系统
type Student struct {
	Name  string
	Age   int
	Score int
}

//将Pupil 和 Graduate 共有的方法也绑定到*Student
func (stu *Student) ShowInfo() {
	fmt.Printf("学生名%v 年龄%v 成绩%v\n", stu.Name, stu.Age, stu.Score)
}
func (stu *Student) SetScore(score int) {
	stu.Score = score
}

//小学生
type Pupil struct {
	Student //嵌入了Student匿名结构体
}

//这是Pupil结构体特有的方法，保留
func (p *Pupil) testing() {
	fmt.Println("小学生正在考试中...")
}

//大学生
type Graduate struct {
	Student //嵌入Student匿名结构体
}

// 这是Graduate结构体特有的方法，保留
func (p *Graduate) testing() {
	fmt.Println("大学生正在考试中...")
}

func main() {
	//当我们对结构体嵌入了匿名结构体使用方法会发生变化
	pupil := &Pupil{}
	pupil.Student.Name = "tom"
	pupil.Student.Age = 8
	pupil.testing()
	pupil.Student.SetScore(70)
	pupil.Student.ShowInfo()

	graduate := &Graduate{}
	graduate.Student.Name = "mary"
	graduate.Student.Age = 18
	graduate.testing()
	graduate.Student.SetScore(100)
	graduate.Student.ShowInfo()
}
